using System;
using System.Data;
using NHibernate.UserTypes;
using Sedna.Domain;
using NHibernate;
using NHibernate.SqlTypes;

namespace Sedna.Core.Persistence
{
	/// <summary>
	/// Hibernate infrastructure class that maps <see cref="MonetaryAmount"/> domain value to the NUMERIC database field.
	/// Note that this mapping class assumes that the amount is always in USD thus completely ingnoring the 
	/// currency check and conversion logic. Please use <see cref="MonetaryAmountType"/> mapping class to map to a multi-currency
	/// database.
	/// This mapping NEVER stores and returns Nulls from the DB. I.e. MonetaryAmount.Default is converted to 0 (zero)
	/// and in case of a NULL in a database, it is converted into USD0 (zero USD)
	/// </summary>
	public class MonetaryAmountUsdType : IUserType
	{
		public object NullSafeGet(IDataReader rs, string[] names, object owner)
		{
			int index = rs.GetOrdinal(names[0]);
			return rs.IsDBNull(index)
				? MonetaryAmount.Default
				: MonetaryAmount.CreateFromFactoredAmount(Convert.ToInt64(NHibernateUtil.Int64.Get(rs, names[0])));
		}

		public void NullSafeSet(IDbCommand cmd, object value, int index)
		{
			MonetaryAmount monetaryAmount = value as MonetaryAmount;
			if(monetaryAmount != null)
			{
				NHibernateUtil.Int64.Set(cmd, monetaryAmount.Amount, index);
			}
			else
			{
				//assume that a value is either a long or can be cast thereto
				NHibernateUtil.Int64.Set(cmd, value!=null?value:0, index);
			}
		}

		public object DeepCopy(object value)
		{
			return value;//MonetaryAmount is immutable, thus deep copy is not needed
		}

		public SqlType[] SqlTypes
		{
			get { return new SqlType[]{NHibernateUtil.Int64.SqlType}; }
		}

		public Type ReturnedType
		{
			get { return typeof(MonetaryAmount); }
		}

		public bool IsMutable
		{
			get { return false; }
		}

		public new bool Equals( object x, object y )
		{
			return x==null?y==null:x.Equals(y);
		}
        public object Disassemble(object value)
        {
            return value;
        }

        public object Assemble(object cached, Object owner)
        {
            return cached;
        }

        public object Replace(object original, object target, object owner)
        {
            return original;
        }

        public int GetHashCode(Object x)
        {
            return x.GetHashCode();
        }


	}
}
